package com.future.admin.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.future.admin.diboot.JoinUtil;
import com.future.admin.mapper.SysUserMapper;
import com.future.admin.service.SysMenuPermissionService;
import com.future.admin.service.SysRoleService;
import com.future.admin.service.SysUserService;
import com.future.admin.service.SysUserTenantService;
import com.future.common.api.admin.entry.*;
import com.future.common.api.admin.vo.SysRoleVO;
import com.future.common.api.admin.vo.SysUserVO;
import com.future.common.api.auth.StatusUser;
import com.future.common.api.auth.UserInfo;
import com.future.common.api.content.VerficationCode;
import com.future.common.api.result.R;
import com.future.common.data.utils.CodeUtils;
import com.future.common.security.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author: liuby5
 * @CreateTime: 2023-05-08  14:21
 * @Description:
 * @Version: 1.0
 */
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Resource
    private SysUserTenantService sysUserTenantService;

    @Resource
    private SysMenuPermissionService sysMenuPermissionService;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    RedisTemplate<String,String> redisTemplate;
    @Override
    public R getLoginUser(String userName) {
        QueryWrapper<SysUser> query = Wrappers.query();
        query.eq("user_name", userName);
        log.info("根据用户姓名获取用户详细信息:{}",userName);
        SysUser one = this.getOne(query);
        if (one == null) {
            return R.failed("未查询到当前用户");
        }
        UserInfo userInfo = new UserInfo();
        // 给用户赋予权限与角色
        log.info("成功获取到用户，开始构建用户权限:{}",userName);
        Map<String, Object> userRoles = this.getUserRoles(one);
        if (!userRoles.containsKey("role")){
            log.info("未获取到有效的用户角色数据:{}",userName);
            return R.failed("未获取到有效的用户角色数据");
        }
        userInfo.setPermissions((String[]) userRoles.get("pre"));
        userInfo.setRoles((Integer[]) userRoles.get("role"));
        com.future.common.api.auth.SysUser sysUser = new com.future.common.api.auth.SysUser();
        sysUser.setUsername(one.getUserName());
        sysUser.setPassword(one.getPassword());
        sysUser.setLockFlag("0");
        sysUser.setUserId(one.getId());
        // 获取用户tenantnId
        QueryWrapper<SysUserTenant> query1 = Wrappers.query();
        query1.eq("user_id", one.getId());
        SysUserTenant one1 = sysUserTenantService.getOne(query1);
        if (one1 == null) {
            return R.failed("未获取到当前用户所在租户");
        }
        sysUser.setTenantId(one1.getTenantId());
        userInfo.setSysUser(sysUser);
        return R.ok(userInfo);
    }

    @Override
    public Map<String, Object> getUserRoles(SysUser sysUser) {
        Map<String, Object> map = new HashMap<>();
        List<Integer> roleNames = new ArrayList<>();
        List<String> permissions = new ArrayList<>();
        // 获取用户角色
        SysUserVO userVO = JoinUtil.entity(sysUser, SysUserVO.class);
        List<SysRole> userRoleLists = userVO.getSysRoleList();
        if (userRoleLists==null || userRoleLists.size()==0){
            log.info("未获取到用户有效的角色数据,无法构建用户:{}",sysUser.getId());
            return map;
        }
        // 获取角色对应的路由
        userRoleLists.forEach(sysRole -> {
            roleNames.add(sysRole.getId());
            SysRoleVO roleVO = JoinUtil.entity(sysRole, SysRoleVO.class);
            List<Integer> menuIds=roleVO.getMenuList().stream().map(SysMenu::getId).collect(Collectors.toList());
            if (menuIds.size() > 0) {
                QueryWrapper<SysMenuPermission> sysMenuPermissionQueryWrapper = Wrappers.query();
                sysMenuPermissionQueryWrapper.in("menu_id", menuIds);
                sysMenuPermissionQueryWrapper.eq("checked","1");
                List<SysMenuPermission> sysMenuPermissions = sysMenuPermissionService.list(sysMenuPermissionQueryWrapper);
                if (sysMenuPermissions != null && sysMenuPermissions.size() > 0) {
                    List<String> permissionList = sysMenuPermissions.stream().map(SysMenuPermission::getPermission).collect(Collectors.toList());
                    permissions.addAll(permissionList);
                }
            }
        });
        String[] pre = new String[permissions.size()];
        permissions.toArray(pre);
        Integer[] role = new Integer[roleNames.size()];
        roleNames.toArray(role);
        map.put("role", role);
        map.put("pre", pre);
        return map;
    }

    @Override
    public R createCode() {
        BufferedImage image = CodeUtils.codeGeneration();
        Map<String, Object> map = new HashMap<>();
//        随机生成uuid
        map.put("uuid", IdUtil.simpleUUID());
        log.info("验证码算式，验证码算式结果【randomString:{},result:{}】", VerficationCode.RANDOM, VerficationCode.CODE_RESULT);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "png", stream);
        }catch (Exception e){
            log.info("图片内容写入异常,无法生成验证码:{}",e.getMessage());
            return R.failed("图片内容写入异常,无法生成验证码");
        }
        String encode = Base64.encode(stream.toByteArray());
        map.put("img", encode);
//        将验证码信息保存在redis中
        redisTemplate.opsForValue().set("java123","123456789");
        String string = redisTemplate.opsForValue().get("java123").toString();
        log.info("是吗:{}",string);
        redisTemplate.opsForValue().set(VerficationCode.CODE_PREFIX, String.valueOf(VerficationCode.CODE_RESULT), 3, TimeUnit.MINUTES);
        return R.ok(map, "登陆验证码生成成功");
    }

    @Override
    public R getUserInfo() {
        StatusUser user = SecurityUtils.getUser();
        SysUser one = this.getById(user.getId());
        SysUserVO entity = JoinUtil.entity(one, SysUserVO.class);
        List<SysRole> userRoleLists = sysRoleService.getUserRoleLists(one);
        entity.setSysRoleList(userRoleLists);
        Map<String, Object> userRoles = this.getUserRoles(one);
        entity.setPermissionList((String[]) userRoles.get("pre"));
        return R.ok(entity);
    }
}
